package com.jm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jm.constants.SystemConstants;
import com.jm.domain.ResponseResult;
import com.jm.domain.entity.LoginUser;
import com.jm.domain.entity.Menu;
import com.jm.domain.entity.RoleMenu;
import com.jm.domain.vo.MenuTreeVo;
import com.jm.domain.vo.MenuVo;
import com.jm.domain.vo.RoleMenuTreeVo;
import com.jm.mapper.MenuMapper;
import com.jm.mapper.RoleMenuMapper;
import com.jm.service.MenuService;
import com.jm.service.RoleMenuService;
import com.jm.utils.BeanCopyUtils;
import com.jm.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author makejava
 * @since 2023-06-24 21:02:45
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {


    @Override
    public ResponseResult getInfo() {
        //
        return null;
    }

    @Override
    public List<String> selectPermsByUserId(Long id) {
        //如果登录用户是管理员，返回所有权限
        if (id == 1L) {
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);
            queryWrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            List<Menu> menus = list(queryWrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回所具有的权限
        return getBaseMapper().selectPermsByUserId(id);
    }

    @Override
    public List<Menu> selectRoutersMenuTreeByUserId(Long userId) {
        List<Menu> menus = null;
        if (userId == 1L) {
            //如果是管理员，查询所有menu
            menus = getBaseMapper().selectAllRoutersMenu();
        } else {
            //否则，查询当前用户所具有的menu
            menus = getBaseMapper().selectRouterMenuTreeByUserId(userId);
        }
        //树状显示
        List<Menu> menuTree = buildMenuTreeDfs(menus, 0L);
//        List<Menu> menuTree = builderMenuTree(menus,0L);
        return menuTree;
    }

    @Override
    public ResponseResult listMenu(String status, String menuName) {
        //查询条件
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!(status == null || status == ""), Menu::getStatus, status);
        queryWrapper.like(!(menuName == null || menuName == ""), Menu::getMenuName, menuName);
        queryWrapper.orderByAsc(Menu::getParentId, Menu::getOrderNum);
        List<Menu> menus = list(queryWrapper);
        //封装vo
        List<MenuVo> menuVos = BeanCopyUtils.copyBeanList(menus, MenuVo.class);
        return ResponseResult.okResult(menuVos);
    }

    @Override
    public ResponseResult getMenuById(Long id) {
        //根据id，查询菜单
        Menu menu = getBaseMapper().selectById(id);
        MenuVo menuVo = BeanCopyUtils.copyBean(menu, MenuVo.class);
        return ResponseResult.okResult(menuVo);
    }

    @Override
    public ResponseResult saveMenu(Menu menu) {
        save(menu);
        return null;
    }

    @Override
    public ResponseResult updateMenu(Menu menu) {
        if (menu.getParentId().equals(menu.getId())) {
            throw new RuntimeException("修改菜单'写博文'失败，上级菜单不能选择自己");
        }
        //更新数据库
        updateById(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult deleteMenuById(Long id) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId, id);
        List<Menu> list = list(queryWrapper);
        if (list.size() > 0) {
            //说明有子节点
            throw new RuntimeException("存在子菜单不允许删除");
        }
        removeById(id);
        return ResponseResult.okResult();
    }

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public ResponseResult treeSelectMenu() {
        //获取登录用户的id
        Long userId = SecurityUtils.getUserId();
        //根据用户id查询菜单权限
        List<MenuTreeVo> menuTreeVos;
        if (userId == 1L) {
            //超级管理员，拥有所有权限
            menuTreeVos = menuMapper.selectALLMenuTreeVo();
        } else {
            //其他管理员
            menuTreeVos = menuMapper.selectMenuTreeVoByUserId(userId);
        }
        //树形显示
        List<MenuTreeVo> menuTreeVoList = buildMenuTreeVo(menuTreeVos, 0L);

        return ResponseResult.okResult(menuTreeVoList);
    }

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public ResponseResult treeSelectMenuByRoleId(Long roleId) {
        if(roleId==1L){
            //超级管理员，拥有所有的menu
            //获取所有的menu列表
            List<MenuTreeVo> menuTreeVos = roleMenuMapper.selectALLMenuTreeVo();
            //菜单树
            List<MenuTreeVo> menuTreeVoList = buildMenuTreeVo(menuTreeVos, 0L);
            //获取menu表中所有的menuId
            List<String> checkedKeys = roleMenuMapper.selectALLMenuIds();
            //封装vo
            RoleMenuTreeVo roleMenuTreeVo = new RoleMenuTreeVo(menuTreeVoList, checkedKeys);
            return ResponseResult.okResult(roleMenuTreeVo);
        }else {
            //根据roleId获取menu列表
            List<MenuTreeVo> menuTreeVos = roleMenuMapper.selectMenuTreeVoByRoleId(roleId);
            //菜单树
            List<MenuTreeVo> menuTreeVoList = buildMenuTreeVo(menuTreeVos, 0L);
            //根据roleId获取menu表中的menuId
            List<String> checkedKeys = roleMenuMapper.selectRoleRelateMenuIds(roleId);
            //封装vo
            RoleMenuTreeVo roleMenuTreeVo = new RoleMenuTreeVo(menuTreeVoList, checkedKeys);
            return ResponseResult.okResult(roleMenuTreeVo);
        }
    }


    private List<MenuTreeVo> buildMenuTreeVo(List<MenuTreeVo> menuTreeVos, Long parentId) {
        List<MenuTreeVo> menuTreeVoList = new ArrayList<>();
        for (int i = 0; i < menuTreeVos.size(); i++) {
            MenuTreeVo menuTreeVo = menuTreeVos.get(i);
            if (menuTreeVo.getParentId().equals(parentId)) {
                menuTreeVo.setChildren(buildMenuTreeVo(menuTreeVos, menuTreeVo.getId()));
                menuTreeVoList.add(menuTreeVo);
            }
        }
        return menuTreeVoList;
    }

    //dfs版：将链表，封装为树形显示
    private List<Menu> buildMenuTreeDfs(List<Menu> menus, Long parentId) {
        List<Menu> retMenus = new ArrayList<>();
        for (int i = 0; i < menus.size(); i++) {
            Menu menu = menus.get(i);
            if (menu.getParentId().equals(parentId)) {
                menu.setChildren(buildMenuTreeDfs(menus, menu.getId()));
                retMenus.add(menu);
            }
        }
        return retMenus;
    }

    //stream流filter过滤器版
    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     *
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}

